package com.atguigu.gmall.payment.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.PaymentType;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.payment.config.AlipayConfig;
import com.atguigu.gmall.payment.service.AlipayService;
import com.atguigu.gmall.payment.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/api/payment/alipay")
@Slf4j
public class AlipayController {
    @Autowired
    private AlipayService alipayService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${app_id}")
    private String app_id;


    @GetMapping("/submit/{orderId}")
    public String submit(@PathVariable Long orderId) {
        String from = "";
        try {
            from = alipayService.submitAlipay(orderId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return from;
    }

    @GetMapping("/callback/return")
    public void returnPaySuccessPage(HttpServletResponse response, @RequestParam HashMap<String, String> map) throws IOException {
        System.out.println("map = " + map);
        response.sendRedirect(AlipayConfig.return_order_url);
    }

    @PostMapping("/callback/notify")
    public String callbackNotify(@RequestParam HashMap<String, String> paramsMap) {
        boolean signVerified = false;
        //调用SDK验证签名
        try {
            signVerified = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
        if (signVerified) {
            // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
            //获取支付宝传过来的outTradeNo
            String outTradeNo = paramsMap.get("out_trade_no");
            //获取支付宝传过来的total_amount订单总金额
            String totalAmount = paramsMap.get("total_amount");
            //获取支付宝传过来的appId
            String appId = paramsMap.get("app_id");
            String notifyId = paramsMap.get("notify_id");
            String tradeStatus = paramsMap.get("trade_status");


            try {
                //验证是否与商家一致
                PaymentInfo paymentInfo = paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
                //判断
//            if (paymentInfo == null || paymentInfo.getTotalAmount().compareTo(new BigDecimal(totalAmount)) != 0) {
//                return "failure";
//            }
                if (paymentInfo == null || new BigDecimal("0.01").compareTo(new BigDecimal(totalAmount)) != 0
                        || !appId.equals(app_id)) {
                    return "failure";
                }

                Boolean result = redisTemplate.opsForValue().setIfAbsent(notifyId, notifyId, 1426, TimeUnit.MINUTES);
                if (!result) {
                    return "failure";
                }
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){
                    paymentService.updatePaymentInfoStatus(outTradeNo, PaymentType.ALIPAY.name(), paramsMap);
                    return "success";
                }
            } catch (Exception e) {
                redisTemplate.delete(notifyId);
                log.error("处理异步通知失败 {}"+outTradeNo);
                throw new RuntimeException(e);
            }

        } else {
            // TODO 验签失败则记录异常日志，并在response中返回failure.
            return "failure";
        }

        return "success";
    }
    @GetMapping("refund/{orderId}")
    public Result refund(@PathVariable(value = "orderId")Long orderId) {
        boolean result = alipayService.refund(orderId);
        return Result.ok(result);
    }

    /**
     * 根据订单ID关闭支付宝交易记录
     * @param orderId 订单ID
     * @return
     */
    @GetMapping("closePay/{orderId}")
    public Boolean closePay(@PathVariable Long orderId){
        Boolean aBoolean = alipayService.closePay(orderId);
        return aBoolean;
    }

    /**
     * 查看是否有交易记录
     * @param orderId
     * @return
     */
    @GetMapping("checkPayment/{orderId}")
    public Boolean checkPayment(@PathVariable Long orderId){
        // 调用退款接口
        boolean flag = alipayService.checkPayment(orderId);
        return flag;
    }

    /**
     * 查看是否有本地交易记录 为什么这里可以直接当参数直接传递进去！
     * @param outTradeNo
     * @return
     */
    @GetMapping("/getPaymentInfo/{outTradeNo}")
    public PaymentInfo getPaymentInfo(@PathVariable String outTradeNo){
        return this.paymentService.getPaymentInfo(outTradeNo,PaymentType.ALIPAY.name());
    }
}
